/* eslint-disable no-case-declarations */
import { remote, shell, nativeImage, ipcRenderer } from 'electron';
import path from 'path';
import url from 'url';
// import createContextMenu from './menu';
import './css.less';
import { asset, isDev, getProtocolUrl } from '../util';
import * as help from './help';
import cfg from './config';
import scan from './scan';
import hotUpdate from './hotUpdate';
import autoUpdate from './autoUpdate';
import book from './book';
import domJSON from './domJSON';

// 修复部分客户端https提示证书不正确
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

const { console: loger, location } = window;
let hasloadURL;
const mainWindow = remote.getCurrentWindow();
const {
  webContents: { session },
  webContents,
} = mainWindow;

const [
  dragRegions,
  webview,
  mainStyle,
  rightBtns,
  btnreload,
  loadStatus,
] = 'dragRegions,mainFrame,mainStyle,rightBtns,reload,loadStatus'.split(',').map((id) => document.getElementById(id));
// 工具栏菜单
const addEvent = (dom, ev, fn, useCapture = false) => dom.addEventListener(ev, fn, useCapture);

const reload = () => {
  setStatus('loading');
  try {
    webview.reload();
  } catch (error) {
    webContents.reload();
  }
};

const btnClick = (e) => {
  const {
    currentTarget: { id: btnId },
  } = e;
  switch (btnId) {
    case 'btnClose':
      mainWindow.hide();
      break;
    case 'btnRestore':
    case 'btnMax':
      if (mainWindow.isMaximized()) {
        mainWindow.restore();
      } else {
        mainWindow.maximize();
      }
      break;
    case 'btnMin':
      mainWindow.minimize();
      break;
    case 'btnBack':
      const webUrl = webview.getURL();
      // 如果是从第三方跳转返回，直接返回跳转前地址
      if (webUrl.includes('jz.hasmartedu.com/login/open/oauth2')) {
        // 创建 URL 对象
        const url = new URL(webUrl);
        // 获取查询参数 redirect_uri 的值
        const redirectUri = url.searchParams.get('redirect_uri');
        console.log('Redirect URI:', decodeURIComponent(redirectUri));
        webview.loadURL(redirectUri);
        return;
      }
      webview.goBack();
      break;
    case 'btnRefresh':
      reload();
      break;
  }
};

const [btnRestore, btnMax] = 'btnRestore,btnMax,btnClose,btnMin,btnRefresh,btnBack'.split(',').map((btnId) => {
  const btn = document.getElementById(btnId);
  addEvent(btn, 'click', btnClick);
  return btn;
});

webview.setAttribute('preload', 'file://' + path.resolve(asset('preload.js')));
let openDevToolsTimer;
let openDevToolsCounter = 0;
addEvent(btnMax, 'mouseup', (e) => {
  if (e.button === 2) {
    if (!openDevToolsTimer) {
      openDevToolsTimer = setTimeout(() => {
        openDevToolsCounter = 0;
        openDevToolsTimer = undefined;
      }, 800);
    }
    openDevToolsCounter++;
    if (openDevToolsCounter >= 5) {
      openDevToolsCounter = 0;
      webContents.openDevTools();
    }
  } else {
    openDevToolsCounter = 0;
    openDevToolsTimer = undefined;
  }
});
addEvent(btnRestore, 'mouseup', (e) => {
  if (e.button === 2) {
    if (!openDevToolsTimer) {
      openDevToolsTimer = setTimeout(() => {
        openDevToolsCounter = 0;
        openDevToolsTimer = undefined;
      }, 500);
    }
    openDevToolsCounter++;
    if (openDevToolsCounter >= 3) {
      openDevToolsCounter = 0;
      webview.openDevTools();
    }
  } else {
    openDevToolsCounter = 0;
    openDevToolsTimer = undefined;
  }
});

// 改变最大化还原图标
const maximizeStateChange = () => {
  loger.debug('maximizeStateChange', mainWindow.isMaximized(), mainWindow.isMinimized());
  if (mainWindow.isMaximized()) {
    btnRestore.classList.remove('hide');
    btnMax.classList.add('hide');
  } else {
    btnRestore.classList.add('hide');
    btnMax.classList.remove('hide');
  }
};
mainWindow.on('maximize', maximizeStateChange);
mainWindow.on('unmaximize', maximizeStateChange);
mainWindow.on('restore', maximizeStateChange);
maximizeStateChange();

/**
 * 设置样式
 * @param {*} styles
 * @param {*} key
 * @param {*} val
 */
const setStyle = (styles, key, val) => {
  if (val === null) {
    styles[key] = null;
  } else if (typeof val === 'number') {
    styles[key] = `${val}px`;
  } else {
    styles[key] = val;
  }
};

/**
 * 拖动区域发生变化
 * @param {*} regions
 */
const dragRegionsChange = (regions) => {
  dragRegions.innerHTML = '';
  if (regions && regions.length) {
    regions.forEach(([top, right, bottom, left, width, height]) => {
      const ele = document.createElement('div');
      setStyle(ele.style, 'left', left);
      setStyle(ele.style, 'top', top);
      setStyle(ele.style, 'right', right);
      setStyle(ele.style, 'bottom', bottom);
      setStyle(ele.style, 'width', width);
      setStyle(ele.style, 'height', height);
      // 测试
      // setStyle(ele.style, 'border', '1px solid red');
      dragRegions.appendChild(ele);
    });
  }
};
const toolBtnsLength = 160;
dragRegionsChange([[3, null, null, 3, `calc(100% - ${toolBtnsLength}px)`, '37px']]);

const getAppInfo = () => {
  return {
    version: cfg.version,
    rightBtnsWidth: rightBtns.clientWidth,
  };
};
// 向客户端发送消息
const send = (...args) => {
  webview.send('ping', ...JSON.parse(JSON.stringify(args)));
};

let loadingTimer;
const setStatus = (status = 'online', msg, title) => {
  clearTimeout(loadingTimer);
  if (status === 'online') {
    dragRegionsChange([]);
  } else {
    dragRegionsChange([
      [3, null, null, 3, `calc(100% - ${toolBtnsLength}px)`, '37px'],
      [3, null, null, 3, 'calc(50% - 200px)', 'calc(100% - 6px)'],
      [50, 3, null, 3, 'calc(100% - 6px)', 'calc(50% - 180px)'],
      [50, 3, null, null, 'calc(50% - 200px)', 'calc(100% - 43px)'],
      [null, 3, 3, 3, 'calc(100% - 6px)', 'calc(50% - 200px)'],
    ]);
  }
  if (status === 'offline') {
    const elePanel = loadStatus.getElementsByClassName(`status${status}`)[0];
    const eleTitle = elePanel && elePanel.getElementsByClassName('title')[0];
    const eleMsg = elePanel && elePanel.getElementsByClassName('msg')[0];
    switch (msg) {
      case 'ERR_CONNECTION_REFUSED':
        title = '服务异常';
        break;
    }
    eleTitle.innerText = title || '网络不通';
    eleMsg.innerText = msg || '抱歉，你访问的页面无法到达';
  } else if (status === 'loading') {
    loadingTimer = setTimeout(() => {
      setStatus('offline');
    }, 20000);
  }
  loadStatus.classList.remove('status404', 'status500', 'statusoffline', 'statusonline', 'statusloading');
  loadStatus.classList.add(`status${status}`);
  loger.info('setStatus', status);
};
// 注册发送消息事件
help.regSendFn(send);
let hasDomReady = false;
addEvent(webview, 'dom-ready', () => {
  if (!hasDomReady) {
    hasDomReady = true;
    if (isDev) {
      webview.openDevTools();
    }
    // 右键菜单
    /*createContextMenu({
      window: webview,
      showCopyImageAddress: true,
      download: (url, opt) => {
        const cid = new Date().getTime();
        if (opt) {
          ipcRenderer.send('downloadOptions', cid, url, opt);
        } else {
          webview.downloadURL(url);
        }
      },
      prepend: (props) => {
        const { editFlags } = props;
        const can = (type) => editFlags[`can${type}`];
        const canSelect = can('SelectAll');
        const canRedo = can('Redo');
        const canUndo = can('Undo');
        return [
          { id: 'selectall', label: '全选', role: canSelect ? 'selectall' : '', visible: canSelect },
          {
            id: 'redo',
            label: '重做',
            role: canRedo ? 'redo' : '',
            enabled: canRedo,
            visible: props.isEditable,
          },
          {
            id: 'undo',
            label: '撤销',
            role: canUndo ? 'undo' : '',
            enabled: canUndo,
            visible: props.isEditable,
          },
        ];
      },
      labels: {
        cut: '剪切',
        copy: '复制',
        paste: '粘贴',
        save: '保存图片',
        saveImageAs: '图片另存为',
        copyLink: '复制链接地址',
        copyImageAddress: '复制图片地址',
        inspect: '调试',
      },
    });*/

    // 第一次启动,检测浏览器参数,发送clientProtocol
    const url = getProtocolUrl(remote.process.argv);
    if (url) {
      help.send('clientProtocol', url);
    }
  }
  send('ready', getAppInfo());
});

addEvent(webview, 'page-title-updated', (e) => {
  document.title = e.title;
});

addEvent(webview, 'did-frame-finish-load', (e) => {
  if (e.isMainFrame) {
    const contents = remote.webContents.fromId(webview.getWebContentsId());
    if (contents) {
      contents.executeJavaScript('location.href', true).then((url) => {
        if (url && url.indexOf('chrome-error') === 0) {
          setStatus('offline', e.errorDescription);
        } else {
          setStatus('online');
        }
      });
    } else {
      setStatus('online');
    }
  }
  send('did-frame-finish-load', { isMainFrame: e.isMainFrame });
});

addEvent(webview, 'did-navigate-in-page', (e) => {
  if (e.isMainFrame) {
    sessionStorage.lastUrl = e.url;
  }
  const uri = url.parse(e.url);
  send('did-navigate-in-page', { isMainFrame: e.isMainFrame, uri });
});
addEvent(webview, 'found-in-page', (result) => {
  send('found-in-page', result);
});

addEvent(webview, 'crashed', (...args) => {
  loger.debug('webview crashed', args);
  window.setTimeout(() => {
    location.reload();
  }, 3000);
});

const sendById = (cid, cmd, ...args) => {
  send(cid ? `${cmd}:${cid}` : cmd, ...args);
};

const errorConvert = (error) => {
  if (error && (error.message || error.code || error.stack)) {
    return {
      error: {
        message: error.message,
        code: error.code,
        name: error.name,
        stack: error.stack,
      },
    };
  }
  return { error };
};
const cmdAlias = {
  openItem: 'openPath',
};

addEvent(webview, 'ipc-message', (e) => {
  // 加入安全域名检查
  // console.debug(e);
  const { args: [cmdx, data, ...args] = [] } = e || {};
  let [cmd, cid] = cmdx.split(':');
  // 接口别名
  cmd = cmdAlias[cmd] || cmd;
  switch (cmd) {
    case 'dragRegions':
      dragRegionsChange(data);
      break;
    case 'title':
      document.title = data;
      break;
    case 'style':
      mainStyle.innerText = data;
      break;
    case 'getZoomLevel':
      webContents.getZoomLevel((zoomLevel) => {
        sendById(cid, 'getZoomLevel', zoomLevel);
      });
      break;
    case 'setZoomLevel':
      webContents.setZoomLevel(data);
      break;
    case 'showItemInFolder':
    case 'openItem':
    case 'openPath':
    case 'trashItem':
    case 'openExternal':
    case 'writeShortcutLink':
    case 'beep':
      sendById(cid, cmd, shell[cmd](data, ...args));
      break;

    case 'isAudioMuted':
      sendById(cid, 'isAudioMuted', webview.isAudioMuted());
      break;
    case 'openDevTools':
    case 'setAudioMuted':
    case 'print':
    case 'findInPage':
    case 'stopFindInPage':
      webview[cmd](data, ...args);
      break;

    case 'printToPDF':
      webview[cmd](data, ...args)
        .catch(errorConvert)
        .then((msg) => {
          sendById(cid, cmd, msg);
        });
      break;
    // 创建教辅工具
    case 'createDrawWindows':
      console.log('case: 创建教辅工具');
      ipcRenderer.send('create-draw-windows');
      break;
    // 销毁教辅工具
    case 'destoryDrawWindows':
      console.log('case: 销毁教辅工具');
      ipcRenderer.send('destory-draw-windows');
      break;
    // 创建openai面板
    case 'openAiPanel':
      console.log('case: 创建AI助手');
      ipcRenderer.send('open-ai-panel', data);
      break;
    // 进入授课模式
    case 'openTeachingMode':
      console.log('case: 进入授课模式');
      ipcRenderer.send('open-teaching-mode');
      break;
    // 接受pc传递的授课资源列表
    case 'setCourseResource':
      console.log('case: 授课资源列表更新 =====> ', data);
      ipcRenderer.send('set-course-resource', data);
      break;
    // 授课模式中页面销毁，需要通知教辅工具做对应的处理
    case 'teachingQuit':
      console.log('case: 退出授课模式');
      ipcRenderer.send('teaching-quit');
      break;
    case 'mainWindowsTouch':
      ipcRenderer.send('main-windows-touch', data);
      break;
    case 'capturePage':
      webview
        .capturePage(data)
        .catch(errorConvert)
        .then((obj) => {
          sendById(cid, 'capturePage', { size: obj.getSize(), img: obj.toDataURL() });
        });
      break;
    case 'close':
    case 'focus':
    case 'blur':
    case 'show':
    case 'showInactive':
    case 'hide':
    case 'maximize':
    case 'unmaximize':
    case 'minimize':
    case 'restore':
    case 'setFullScreen':
    case 'setAlwaysOnTop':
    case 'center':
    case 'setProgressBar':
    case 'setOpacity':
    case 'setMinimumSize':
    case 'setMaximumSize':
      mainWindow[cmd](data, ...args);
      break;
    case 'setIcon':
      mainWindow.setIcon(nativeImage.createFromDataURL(data));
      break;
    case 'isMaximized':
    case 'isMinimized':
    case 'isFullScreen':
    case 'isAlwaysOnTop':
    case 'getMinimumSize':
    case 'getOpacity':
    case 'getMaximumSize':
      sendById(cid, cmd, mainWindow[cmd]());
      break;

    case 'setThumbarButtons':
      if (data) {
        mainWindow.setThumbarButtons(
          data.map((btn) => {
            return {
              ...btn,
              icon: btn.icon && nativeImage.createFromDataURL(btn.icon),
            };
          }),
        );
      }
      break;
    case 'getCacheSize':
    case 'clearCache':
    case 'clearStorageData':
      session[cmd]((size) => {
        sendById(cid, cmd, size);
      });
      break;

    case 'flushStorageData':
    case 'createInterruptedDownload':
      session[cmd](data, ...args);
      break;

    case 'scanSources':
    case 'scanClose':
    case 'scanStart':
    case 'scanFiles':
    case 'scanFile':
    case 'scanUpload':
    case 'scanDel':
    case 'scanDelAll':
    case 'scanOpenDir':
    case 'scanQr':
    case 'scanFileMove':
    case 'scanFilesEx':
    case 'scanUploadEx':
      scan[cmd](data, ...args)
        .catch(errorConvert)
        .then((msg) => {
          sendById(cid, cmd, msg);
        });

      break;
    case 'hotCheck':
    case 'hotUpdate':
      hotUpdate[cmd](data, ...args)
        .catch(errorConvert)
        .then((msg) => {
          sendById(cid, cmd, msg);
        });
      break;
    case 'getCfg':
      sendById(cid, cmd, cfg);
      break;
    case 'checkForUpdates':
    case 'quitAndInstall':
      autoUpdate[cmd](data, ...args)
        .catch(errorConvert)
        .then((msg) => {
          sendById(cid, cmd, msg);
        });
      break;
    case 'bookList':
    case 'bookInstall':
    case 'bookOpen':
    case 'bookChaptersGet':
    case 'bookUninstall':
    case 'bookDownloadCancel':
      book[cmd](data, ...args)
        .catch(errorConvert)
        .then((msg) => {
          sendById(cid, cmd, msg);
        });
      break;
    case 'download':
      if (data) {
        if (args[0]) {
          ipcRenderer.send('downloadOptions', cid, data, ...args);
        } else {
          webview.downloadURL(data);
          sendById(cid, 'download', true);
        }
      } else {
        sendById(cid, 'download', false);
      }
      break;
  }
});

// clientOpenPage 监听客户端侧边栏点击事件
// clientQuit 监听侧边栏点击退出事件
// resourceChange 客户端授课资源点击对应的资源
// getSourceData 主动向客户端发起资源请求
// callwsOrder 客户端发送websocket命令到渲染进程
['clientOpenPage', 'clientQuit', 'resourceChange', 'getSourceData', 'callwsOrder', 'callwsFiles'].forEach((v) => {
  ipcRenderer.on(v, (e, ...args) => {
    help.send(v, args);
  });
});

/**
 * 下载消息
 */
ipcRenderer.on('download', (e, ...args) => send('download', ...args));

/**
 * 唤醒客户端参数接收
 */
ipcRenderer.on('clientProtocol', (event, url) => {
  help.send('clientProtocol', url);
});

/**
 * 下载选项消息
 */
ipcRenderer.on('downloadOptions', (e, cid, url) => {
  webview.downloadURL(url);
  sendById(cid, 'download', true);
});

ipcRenderer.on('reload', reload);
ipcRenderer.on('reloadIgnoringCache', () => {
  try {
    webview.reloadIgnoringCache()();
  } catch (error) {
    webContents.reloadIgnoringCache();
  }
});

const loadUrl = () => {
  if (!hasloadURL) {
    if (navigator.onLine) {
      hasloadURL = true;
      setStatus('loading');
      const url = sessionStorage.lastUrl || cfg.urlApp;
      webview.setAttribute('src', url);
    } else {
      setStatus('offline');
    }
  }
};

const updateOnlineStatus = () => {
  ipcRenderer.send('online-status-changed', navigator.onLine);
  loadUrl();
};

addEvent(window, 'online', updateOnlineStatus);
addEvent(window, 'offline', updateOnlineStatus);
addEvent(btnreload, 'click', () => {
  if (hasloadURL) {
    reload();
  } else {
    loadUrl();
  }
});
updateOnlineStatus();

const customUi = document.getElementById('customUi');
const mainTitleEvent = function (e) {
  const {
    altKey,
    bubbles,
    button,
    buttons,
    cancelBubble,
    cancelable,
    clientX,
    clientY,
    composed,
    ctrlKey,
    defaultPrevented,
    detail,
    eventPhase,
    layerX,
    layerY,
    metaKey,
    movementX,
    movementY,
    offsetX,
    offsetY,
    pageX,
    pageY,
    returnValue,
    screenX,
    screenY,
    shiftKey,
    type,
    which,
    x,
    y,
    target,
  } = e;
  help.send('customUi', {
    altKey,
    bubbles,
    button,
    buttons,
    cancelBubble,
    cancelable,
    clientX,
    clientY,
    composed,
    ctrlKey,
    defaultPrevented,
    detail,
    eventPhase,
    layerX,
    layerY,
    metaKey,
    movementX,
    movementY,
    offsetX,
    offsetY,
    pageX,
    pageY,
    returnValue,
    screenX,
    screenY,
    shiftKey,
    type,
    which,
    x,
    y,
    target: domJSON.toJSON(target, { attributes: false, metadata: false }),
  });
};
addEvent(customUi, 'click', mainTitleEvent);
addEvent(customUi, 'mousedown', mainTitleEvent);
addEvent(customUi, 'mousemove', mainTitleEvent);
addEvent(customUi, 'mouseout', mainTitleEvent);
addEvent(customUi, 'mouseup', mainTitleEvent);
addEvent(customUi, 'mousewheel', mainTitleEvent);
